css: implement font-variant as a shorthand
authorMatthias Clasen <mclasen@redhat.com>
Mon, 18 Sep 2017 15:28:05 +0000 (11:28 -0400)
committerMatthias Clasen <mclasen@redhat.com>
Mon, 18 Sep 2017 18:27:06 +0000 (14:27 -0400)
Drop the current css2-style font-variant property and
replace it with a shorthand as specified in the css3 fonts
module. Currently, we fully support the font-variant-ligatures,
font-variant-position, font-variant-caps, font-variant-numeric
and font-variant-east-asian subproperties. font-variant-alternatives
is only partially supported.

gtk/gtkcssarrayvalue.c
gtk/gtkcssenumvalue.c
gtk/gtkcssenumvalueprivate.h
gtk/gtkcssshorthandpropertyimpl.c
gtk/gtkcssstylepropertyimpl.c
gtk/gtkcsstypesprivate.h

index edda8866031bc36307995adda682e188bdc794ff..c1a94c7236cb6ac6848093d56b9e0c7ef8d9633d 100644 (file)
@@ -244,7 +244,6 @@ gtk_css_value_array_transition (GtkCssValue *start,
     case GTK_CSS_PROPERTY_BACKGROUND_COLOR:
     case GTK_CSS_PROPERTY_FONT_FAMILY:
     case GTK_CSS_PROPERTY_FONT_STYLE:
-    case GTK_CSS_PROPERTY_FONT_VARIANT:
     case GTK_CSS_PROPERTY_FONT_WEIGHT:
     case GTK_CSS_PROPERTY_TEXT_SHADOW:
     case GTK_CSS_PROPERTY_ICON_SHADOW:
index 81e238da39d5c2da31a0d02a2918cd94558fd909..b4b31daa745de914be731695e5c13f38d575dc71 100644 (file)
@@ -376,53 +376,6 @@ _gtk_css_font_style_value_get (const GtkCssValue *value)
   return value->value;
 }
 
-/* PangoVariant */
-
-static const GtkCssValueClass GTK_CSS_VALUE_FONT_VARIANT = {
-  gtk_css_value_enum_free,
-  gtk_css_value_enum_compute,
-  gtk_css_value_enum_equal,
-  gtk_css_value_enum_transition,
-  gtk_css_value_enum_print
-};
-
-static GtkCssValue font_variant_values[] = {
-  { &GTK_CSS_VALUE_FONT_VARIANT, 1, PANGO_VARIANT_NORMAL, "normal" },
-  { &GTK_CSS_VALUE_FONT_VARIANT, 1, PANGO_VARIANT_SMALL_CAPS, "small-caps" }
-};
-
-GtkCssValue *
-_gtk_css_font_variant_value_new (PangoVariant font_variant)
-{
-  g_return_val_if_fail ((gint)font_variant < G_N_ELEMENTS (font_variant_values), NULL);
-
-  return _gtk_css_value_ref (&font_variant_values[font_variant]);
-}
-
-GtkCssValue *
-_gtk_css_font_variant_value_try_parse (GtkCssParser *parser)
-{
-  guint i;
-
-  g_return_val_if_fail (parser != NULL, NULL);
-
-  for (i = 0; i < G_N_ELEMENTS (font_variant_values); i++)
-    {
-      if (_gtk_css_parser_try (parser, font_variant_values[i].name, TRUE))
-        return _gtk_css_value_ref (&font_variant_values[i]);
-    }
-
-  return NULL;
-}
-
-PangoVariant
-_gtk_css_font_variant_value_get (const GtkCssValue *value)
-{
-  g_return_val_if_fail (value->class == &GTK_CSS_VALUE_FONT_VARIANT, PANGO_VARIANT_NORMAL);
-
-  return value->value;
-}
-
 /* PangoWeight */
 
 #define BOLDER -1
index 5b6c6f393c381b035e450ad954f652c59c1276f4..bdb4d2aebbfdb3cb6083b825178fee6421a04b8a 100644 (file)
@@ -45,10 +45,6 @@ GtkCssValue *   _gtk_css_font_style_value_new         (PangoStyle         style)
 GtkCssValue *   _gtk_css_font_style_value_try_parse   (GtkCssParser      *parser);
 PangoStyle      _gtk_css_font_style_value_get         (const GtkCssValue *value);
 
-GtkCssValue *   _gtk_css_font_variant_value_new       (PangoVariant       variant);
-GtkCssValue *   _gtk_css_font_variant_value_try_parse (GtkCssParser      *parser);
-PangoVariant    _gtk_css_font_variant_value_get       (const GtkCssValue *value);
-
 GtkCssValue *   _gtk_css_font_weight_value_new        (PangoWeight        weight);
 GtkCssValue *   _gtk_css_font_weight_value_try_parse  (GtkCssParser      *parser);
 PangoWeight     _gtk_css_font_weight_value_get        (const GtkCssValue *value);
index 845e31b30840b0aa88caf68456113025c2d79646..c2081f48cbd1ec2c27520a8f19657a704f625249 100644 (file)
@@ -416,6 +416,16 @@ parse_border (GtkCssShorthandProperty  *shorthand,
   return TRUE;
 }
 
+static GtkCssValue *
+_gtk_css_font_variant_value_try_parse (GtkCssParser *parser)
+{
+  if (_gtk_css_parser_try (parser, "normal", TRUE))
+    return _gtk_css_ident_value_new ("normal");
+  else if (_gtk_css_parser_try (parser, "small-caps", TRUE))
+    return _gtk_css_ident_value_new ("small-caps");
+  return NULL;
+}
+
 static gboolean
 parse_font (GtkCssShorthandProperty  *shorthand,
             GtkCssValue             **values,
@@ -856,6 +866,219 @@ parse_text_decoration (GtkCssShorthandProperty  *shorthand,
   return TRUE;
 }
 
+static gboolean
+parse_font_variant (GtkCssShorthandProperty  *shorthand,
+                    GtkCssValue             **values,
+                    GtkCssParser             *parser)
+{
+  if (_gtk_css_parser_try (parser, "normal", TRUE))
+    {
+      /* all initial values */
+    }
+  else if (_gtk_css_parser_try (parser, "none", TRUE))
+    {
+      /* all initial values, except for font-variant-ligatures */
+      values[0] = _gtk_css_array_value_new (_gtk_css_ident_value_new ("none"));
+    }
+  else
+    {
+      gboolean found;
+      GtkCssValue *lig_values[4] = { NULL, NULL, NULL, NULL };
+      guint n_ligs = 0;
+      gboolean common = FALSE;
+      gboolean discretionary = FALSE;
+      gboolean historical = FALSE;
+      gboolean contextual = FALSE;
+      GtkCssValue *num_values[5] = { NULL, NULL, NULL, NULL };
+      guint n_num = 0;
+      gboolean figure = FALSE;
+      gboolean spacing = FALSE;
+      gboolean fraction = FALSE;
+      gboolean ordinal = FALSE;
+      gboolean zero = FALSE;
+      GtkCssValue *alt_value;
+      GtkCssValue *ea_values[5] = { NULL, NULL, NULL, NULL };
+      guint n_ea = 0;
+      gboolean variant = FALSE;
+      gboolean width = FALSE;
+      gboolean ruby = FALSE;
+
+      do {
+        found = FALSE;
+        if (!common)
+          {
+            lig_values[n_ligs] = _gtk_css_ident_value_try (parser, "common-ligatures",
+                                                                   "no-common-ligatures", NULL);
+            if (lig_values[n_ligs])
+              {
+                n_ligs++;
+                common = TRUE;
+                found = TRUE;
+              }
+          }
+        if (!discretionary)
+          {
+            lig_values[n_ligs] = _gtk_css_ident_value_try (parser, "discretionary-ligatures",
+                                                                   "no-discretionary-ligatures", NULL);
+            if (lig_values[n_ligs])
+              {
+                n_ligs++;
+                discretionary = TRUE;
+                found = TRUE;
+              }
+          }
+        if (!historical)
+          {
+            lig_values[n_ligs] = _gtk_css_ident_value_try (parser, "historical-ligatures",
+                                                                   "no-historical-ligatures", NULL);
+            if (lig_values[n_ligs])
+              {
+                n_ligs++;
+                historical = TRUE;
+                found = TRUE;
+              }
+          }
+        if (!contextual)
+          {
+            lig_values[n_ligs] = _gtk_css_ident_value_try (parser, "contextual",
+                                                                   "no-contextual", NULL);
+            if (lig_values[n_ligs])
+              {
+                n_ligs++;
+                contextual = TRUE;
+                found = TRUE;
+              }
+          }
+
+        if (!figure)
+          {
+            num_values[n_num] = _gtk_css_ident_value_try (parser, "lining-nums",
+                                                                  "oldstyle-nums", NULL);
+            if (num_values[n_num])
+              {
+                n_num++;
+                figure = TRUE;
+                found = TRUE;
+              }
+          }
+        if (!spacing)
+          {
+            num_values[n_num] = _gtk_css_ident_value_try (parser, "proportional-nums",
+                                                                  "tabular-nums", NULL);
+            if (num_values[n_num])
+              {
+                n_num++;
+                spacing = TRUE;
+                found = TRUE;
+              }
+          }
+        if (!fraction)
+          {
+            num_values[n_num] = _gtk_css_ident_value_try (parser, "diagonal-fractions",
+                                                                  "stacked-fractions", NULL);
+            if (num_values[n_num])
+              {
+                n_num++;
+                fraction = TRUE;
+                found = TRUE;
+              }
+          }
+        if (!ordinal)
+          {
+            num_values[n_num] = _gtk_css_ident_value_try (parser, "ordinal", NULL);
+            if (num_values[n_num])
+              {
+                n_num++;
+                ordinal = TRUE;
+                found = TRUE;
+              }
+          }
+        if (!zero)
+          {
+            num_values[n_num] = _gtk_css_ident_value_try (parser, "slashed-zero", NULL);
+            if (num_values[n_num])
+              {
+                n_num++;
+                zero = TRUE;
+                found = TRUE;
+              }
+          }
+        if (alt_value == NULL)
+          {
+            alt_value = _gtk_css_ident_value_try (parser, "historical-forms", NULL);
+            if (alt_value)
+              found = TRUE;
+          }
+
+        if (values[1] == NULL)
+          {
+            values[1] = _gtk_css_ident_value_try (parser, "sub", "super", NULL);
+            if (values[1])
+              found = TRUE;
+          }
+        if (values[2] == NULL)
+          {
+            values[2] = _gtk_css_ident_value_try (parser, "small-caps", "all-small-caps",
+                                                          "petite-caps", "all-petite-caps",
+                                                          "unicase", "titling-caps", NULL);
+            if (values[2])
+              found = TRUE;
+          }
+
+        if (!variant)
+          {
+            ea_values[n_ea] = _gtk_css_ident_value_try (parser, "jis78", "jis83", "jis90", "jis04",
+                                                        "simplified", "traditional", NULL);
+            if (ea_values[n_ea])
+              {
+                n_ea++;
+                variant = TRUE;
+              }
+         }
+        if (!width)
+          {
+            ea_values[n_ea] = _gtk_css_ident_value_try (parser, "full-width"
+                                                                "proportional-width", NULL);
+            if (ea_values[n_ea])
+              {
+                n_ea++;
+                width = TRUE;
+              }
+         }
+        if (!ruby)
+          {
+            ea_values[n_ea] = _gtk_css_ident_value_try (parser, "ruby", NULL);
+            if (ea_values[n_ea])
+              {
+                n_ea++;
+                ruby = TRUE;
+              }
+         }
+
+
+        if (!found)
+          {
+            _gtk_css_parser_error (parser, "Unknown value for property");
+            return FALSE;
+          }
+      } while (!value_is_done_parsing (parser));
+
+      if (n_ligs > 0)
+        values[0] = _gtk_css_array_value_new_from_array (lig_values, n_ligs);
+
+      if (n_num > 0)
+        values[3] = _gtk_css_array_value_new_from_array (num_values, n_num);
+
+      if (alt_value)
+        values[4] = _gtk_css_array_value_new (alt_value);
+
+      if (n_ea > 0)
+        values[5] = _gtk_css_array_value_new_from_array  (ea_values, n_ea);
+    }
+
+  return TRUE;
+}
+
 static gboolean
 parse_all (GtkCssShorthandProperty  *shorthand,
            GtkCssValue             **values,
@@ -949,10 +1172,6 @@ pack_font_description (GtkCssShorthandProperty *shorthand,
   if (v)
     pango_font_description_set_style (description, _gtk_css_font_style_value_get (v));
 
-  v = (* query_func) (_gtk_css_style_property_get_id (GTK_CSS_STYLE_PROPERTY (_gtk_style_property_lookup ("font-variant"))), query_data);
-  if (v)
-    pango_font_description_set_variant (description, _gtk_css_font_variant_value_get (v));
-
   v = (* query_func) (_gtk_css_style_property_get_id (GTK_CSS_STYLE_PROPERTY (_gtk_style_property_lookup ("font-weight"))), query_data);
   if (v)
     pango_font_description_set_weight (description, _gtk_css_font_weight_value_get (v));
@@ -1027,7 +1246,7 @@ void
 _gtk_css_shorthand_property_init_properties (void)
 {
   /* The order is important here, be careful when changing it */
-  const char *font_subproperties[] = { "font-family", "font-style", "font-variant", "font-weight", "font-stretch", "font-size", NULL };
+  const char *font_subproperties[] = { "font-family", "font-style", "font-variant-caps", "font-weight", "font-stretch", "font-size", NULL };
   const char *margin_subproperties[] = { "margin-top", "margin-right", "margin-bottom", "margin-left", NULL };
   const char *padding_subproperties[] = { "padding-top", "padding-right", "padding-bottom", "padding-left", NULL };
   const char *border_width_subproperties[] = { "border-top-width", "border-right-width", "border-bottom-width", "border-left-width", NULL };
@@ -1053,6 +1272,7 @@ _gtk_css_shorthand_property_init_properties (void)
   const char *animation_subproperties[] = { "animation-name", "animation-iteration-count", "animation-duration", "animation-delay", 
                                             "animation-timing-function", "animation-direction", "animation-fill-mode", NULL };
   const char *text_decoration_subproperties[] = { "text-decoration-line", "text-decoration-style", "text-decoration-color", NULL };
+  const char *font_variant_subproperties[] = { "font-variant-ligatures", "font-variant-position", "font-variant-caps", "font-variant-numeric", "font-variant-alternatives", "font-variant-east-asian", NULL };
 
   const char **all_subproperties;
 
@@ -1151,6 +1371,11 @@ _gtk_css_shorthand_property_init_properties (void)
                                           text_decoration_subproperties,
                                           parse_text_decoration,
                                           NULL);
+  _gtk_css_shorthand_property_register   ("font-variant",
+                                          G_TYPE_NONE,
+                                          font_variant_subproperties,
+                                          parse_font_variant,
+                                          NULL);
 
   all_subproperties = get_all_subproperties ();
   _gtk_css_shorthand_property_register   ("all",
index a81a5a25072df0699cdc4575c3287507fb93fc26..adc7ea35efe25335c2d14433fab1b4474f7b27c6 100644 (file)
@@ -259,27 +259,6 @@ font_weight_query (GtkCssStyleProperty *property,
   g_value_set_enum (value, _gtk_css_font_weight_value_get (css_value));
 }
 
-static GtkCssValue *
-font_variant_parse (GtkCssStyleProperty *property,
-                    GtkCssParser        *parser)
-{
-  GtkCssValue *value = _gtk_css_font_variant_value_try_parse (parser);
-  
-  if (value == NULL)
-    _gtk_css_parser_error (parser, "unknown value for property");
-
-  return value;
-}
-
-static void
-font_variant_query (GtkCssStyleProperty *property,
-                    const GtkCssValue   *css_value,
-                     GValue              *value)
-{
-  g_value_init (value, PANGO_TYPE_VARIANT);
-  g_value_set_enum (value, _gtk_css_font_variant_value_get (css_value));
-}
-
 static GtkCssValue *
 font_stretch_parse (GtkCssStyleProperty *property,
                     GtkCssParser        *parser)
@@ -1238,14 +1217,6 @@ _gtk_css_style_property_init_properties (void)
                                           font_style_parse,
                                           font_style_query,
                                           _gtk_css_font_style_value_new (PANGO_STYLE_NORMAL));
-  gtk_css_style_property_register        ("font-variant",
-                                          GTK_CSS_PROPERTY_FONT_VARIANT,
-                                          PANGO_TYPE_VARIANT,
-                                          GTK_STYLE_PROPERTY_INHERIT,
-                                          GTK_CSS_AFFECTS_FONT | GTK_CSS_AFFECTS_TEXT,
-                                          font_variant_parse,
-                                          font_variant_query,
-                                          _gtk_css_font_variant_value_new (PANGO_VARIANT_NORMAL));
   gtk_css_style_property_register        ("font-weight",
                                           GTK_CSS_PROPERTY_FONT_WEIGHT,
                                           PANGO_TYPE_WEIGHT,
index 8e939f3c67d459102080cb5022aacc1fec4f0f4d..a7fe8c9d7dbfed1a566e1e6a6c58449acbceb837 100644 (file)
@@ -156,7 +156,6 @@ enum { /*< skip >*/
   GTK_CSS_PROPERTY_BACKGROUND_COLOR,
   GTK_CSS_PROPERTY_FONT_FAMILY,
   GTK_CSS_PROPERTY_FONT_STYLE,
-  GTK_CSS_PROPERTY_FONT_VARIANT,
   GTK_CSS_PROPERTY_FONT_WEIGHT,
   GTK_CSS_PROPERTY_FONT_STRETCH,
   GTK_CSS_PROPERTY_LETTER_SPACING,